
package com.jf.cloud.multishop.controller.multishop;


import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSONObject;
import com.jf.cloud.api.multishop.constant.ShopStatus;
import com.jf.cloud.api.multishop.vo.ShopDetailVO;
import com.jf.cloud.api.platform.constant.OfflineHandleEventType;
import com.jf.cloud.api.platform.dto.OfflineHandleEventDTO;
import com.jf.cloud.api.platform.feign.OfflineHandleEventFeignClient;
import com.jf.cloud.api.platform.vo.OfflineHandleEventVO;
import com.jf.cloud.common.cache.util.RedisUtil;
import com.jf.cloud.common.constant.Constant;
import com.jf.cloud.common.exception.LuckException;
import com.jf.cloud.common.response.ServerResponseEntity;
import com.jf.cloud.common.security.AuthUserContext;
import com.jf.cloud.multishop.dto.ShopDetailDTO;
import com.jf.cloud.multishop.service.ShopDetailService;
import com.jf.cloud.multishop.vo.ShopStatusInfoVO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.codec.binary.Base64;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;

/**
 * @author zz
 */
@RestController("multishopShopDetailController")
@RequestMapping("/m/apply_shop/shop_detail")
@Tag(name = "multishop-店铺信息")
public class ShopDetailController {
    private final Logger logger = LoggerFactory.getLogger(ShopDetailController.class);

    @Autowired
    private ShopDetailService shopDetailService;
    @Autowired
    private OfflineHandleEventFeignClient offlineHandleEventFeignClient;


    @PostMapping
    @Operation(summary = "创建店铺", description = "创建店铺")
    public ServerResponseEntity<Void> createShop(@RequestBody @Valid ShopDetailDTO shopDetailDTO) {
        if (!Objects.equals(AuthUserContext.get().getTenantId(), Constant.DEFAULT_SHOP_ID)) {
            throw new LuckException("店铺已存在,不能重复创建");
        }
        this.dealWithUpdateOrCreateInfo(shopDetailDTO);
        shopDetailService.createShop(shopDetailDTO);
        return ServerResponseEntity.success();
    }

    @PutMapping
    @Operation(summary = "更新店铺基本信息", description = "更新店铺基本信息")
    public ServerResponseEntity<Void> update(@RequestBody @Valid ShopDetailDTO shopDetailDTO) {
        Long shopId = AuthUserContext.get().getTenantId();
        if (Objects.equals(shopId, Constant.DEFAULT_SHOP_ID)) {
            throw new LuckException("店铺不存在,无法更新");
        }
        shopDetailDTO.setShopId(shopId);
        this.dealWithUpdateOrCreateInfo(shopDetailDTO);
        shopDetailService.update(shopDetailDTO);
        return ServerResponseEntity.success();
    }

    @PostMapping("/storage")
    @Operation(summary = "存储店铺基本信息", description = "存储店铺基本信息,不存在则新增，已存在则更新")
    public ServerResponseEntity<Void> storage(@RequestBody @Valid ShopDetailDTO shopDetailDTO) {
        Long shopId = AuthUserContext.get().getTenantId();
        this.dealWithUpdateOrCreateInfo(shopDetailDTO);
        if (Objects.equals(shopId, Constant.DEFAULT_SHOP_ID)) {
            // 店铺不存在，新增
            shopDetailService.createShop(shopDetailDTO);
        } else {
            // 店铺已存在，更新
            shopDetailDTO.setShopId(shopId);
            shopDetailService.update(shopDetailDTO);
        }
        return ServerResponseEntity.success();
    }

    @GetMapping
    @Operation(summary = "获取店铺基本信息", description = "获取店铺基本信息")
    public ServerResponseEntity<ShopDetailVO> get() {
        Long shopId = AuthUserContext.get().getTenantId();
        if (Objects.equals(shopId, Constant.DEFAULT_SHOP_ID)) {
            // 店铺未创建
            return ServerResponseEntity.success(null);
        }
        return ServerResponseEntity.success(shopDetailService.getByShopId(shopId));
    }

    @GetMapping("/getQrCode")
    @Operation(summary = "获取店铺收款码", description = "获取店铺收款码")
    public ServerResponseEntity<?> getQrCode(String appid, String page,String version ) {
//        {
//            "page": "package-qrcode/shop/paycode/index",
//                "scene": "id=shopId",
//                "check_path": true,
//                "env_version": "trial"
//        }
        Long shopId = AuthUserContext.get().getTenantId();
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("page", page);
        jsonObject.put("scene", "shopId=" + shopId);
        jsonObject.put("check_path", false);
        jsonObject.put("env_version", version);

        //根据API的要求，定义相对应的Content-Type
        logger.info("请求token" + url + "?access_token=" + RedisUtil.get("wxMa:access_token:" + appid));
        HttpResponse response = HttpUtil.createPost(url + "?access_token=" + RedisUtil.get("wxMa:access_token:" + appid)).contentType("application/json").body(jsonObject.toJSONString()).execute();
        InputStream in=response.bodyStream();
        byte[] data = null;
        // 读取图片字节数组
        try {
            //创建字节数组输出流作为中转仓库，等待被写入数据
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = in.read(buff, 0, 100)) > 0) {
                //向中转的输出流循环写出输入流中的数据
                swapStream.write(buff, 0, rc);
            }
            //此时connection的输入流返回给我们的请求结果数据已经被完全地写入了我们定义的中转输出流swapStream中
            data = swapStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String base64Code = new String(Objects.requireNonNull(Base64.encodeBase64(data)));
        return ServerResponseEntity.success(base64Code);
    }

    @GetMapping("/getSceneQrCode")
    @Operation(summary = "获取小程序码", description = "获取小程序码")
    public ServerResponseEntity<?> getSceneQrCode(String appid, String page,String version,String scene) {
        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit";
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("page", page);
        jsonObject.put("scene", scene);
        jsonObject.put("check_path", false);
        jsonObject.put("env_version", version);
        //根据API的要求，定义相对应的Content-Type
        logger.info("请求token" + url + "?access_token=" + RedisUtil.get("wxMa:access_token:" + appid));
        HttpResponse response = HttpUtil.createPost(url + "?access_token=" + RedisUtil.get("wxMa:access_token:" + appid)).contentType("application/json").body(jsonObject.toJSONString()).execute();
        InputStream in=response.bodyStream();
        byte[] data = null;
        // 读取图片字节数组
        try {
            //创建字节数组输出流作为中转仓库，等待被写入数据
            ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
            byte[] buff = new byte[100];
            int rc = 0;
            while ((rc = in.read(buff, 0, 100)) > 0) {
                //向中转的输出流循环写出输入流中的数据
                swapStream.write(buff, 0, rc);
            }
            //此时connection的输入流返回给我们的请求结果数据已经被完全地写入了我们定义的中转输出流swapStream中
            data = swapStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        String base64Code = new String(Objects.requireNonNull(Base64.encodeBase64(data)));
        return ServerResponseEntity.success(base64Code);
    }


    @GetMapping("/get_status_info")
    @Operation(summary = "获取店铺状态信息", description = "获取店铺状态信息")
    public ServerResponseEntity<ShopStatusInfoVO> getShopStatusInfo() {
        Long shopId = AuthUserContext.get().getTenantId();
        ShopDetailVO shopDetailVO = shopDetailService.getByShopId(shopId);
        if (Objects.isNull(shopDetailVO)) {
            throw new LuckException("店铺不存在");
        }
        ShopStatusInfoVO shopStatusInfoVO = new ShopStatusInfoVO();
        shopStatusInfoVO.setShopStatus(shopDetailVO.getShopStatus());
        shopStatusInfoVO.setContractStartTime(shopDetailVO.getContractStartTime());
        shopStatusInfoVO.setContractEndTime(shopDetailVO.getContractEndTime());
        if (Objects.equals(shopDetailVO.getShopStatus(), ShopStatus.OFFLINE.value())) {
            ServerResponseEntity<OfflineHandleEventVO> offlineHandleEventRes = offlineHandleEventFeignClient.getProcessingEventByHandleTypeAndHandleId(OfflineHandleEventType.SHOP.getValue(), shopId, null);
            if (offlineHandleEventRes.isFail()) {
                throw new LuckException(offlineHandleEventRes.getMsg());
            }
            OfflineHandleEventVO offlineHandleEventVO = offlineHandleEventRes.getData();
            if (Objects.nonNull(offlineHandleEventVO)) {
                shopStatusInfoVO.setOfflineStatus(offlineHandleEventVO.getStatus());
                shopStatusInfoVO.setOfflineReason(offlineHandleEventVO.getOfflineReason());
            }
        }
        return ServerResponseEntity.success(shopStatusInfoVO);
    }

    @PostMapping("/audit_apply")
    @Operation(summary = "店铺重新申请上线", description = "店铺重新申请上线")
    public ServerResponseEntity<Void> auditApply(@RequestBody OfflineHandleEventDTO offlineHandleEventDTO) {
        Long shopId = AuthUserContext.get().getTenantId();
        offlineHandleEventDTO.setHandleId(shopId);
        shopDetailService.auditApply(offlineHandleEventDTO);
        return ServerResponseEntity.success();
    }

    /**
     * 处理店铺信息，这些信息商家无法直接修改
     *
     * @param shopDetailDTO
     */
    private void dealWithUpdateOrCreateInfo(ShopDetailDTO shopDetailDTO) {
        if (Objects.isNull(shopDetailDTO)) {
            return;
        }
        shopDetailDTO.setContractEndTime(null);
        shopDetailDTO.setContractStartTime(null);
        shopDetailDTO.setShopStatus(null);
        shopDetailDTO.setType(null);
    }
}
